package com.luo.ai.assistant.file.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.luo.ai.assistant.file.FileConvertor;
import com.luo.ai.assistant.file.FileDetailService;
import com.luo.ai.assistant.file.dao.FileDetailMapper;
import com.luo.ai.assistant.file.dao.FilePartDetailMapper;
import com.luo.ai.assistant.file.model.FileDetail;
import com.luo.ai.assistant.file.model.FileDetailQuery;
import com.luo.ai.assistant.file.model.FilePartDetail;
import com.luo.ai.assistant.file.model.TrainStatusEnum;
import org.dromara.x.file.storage.core.FileInfo;
import org.dromara.x.file.storage.core.upload.FilePartInfo;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * 用来将文件上传记录保存到数据库，这里使用了 MyBatis-Plus 和 Hutool 工具类
 *
 * @author luohq
 * @date 2025-01-07
 * @link <a href="https://x-file-storage.xuyanwu.cn/#/%E5%9F%BA%E7%A1%80%E5%8A%9F%E8%83%BD?id=%e4%bf%9d%e5%ad%98%e4%b8%8a%e4%bc%a0%e8%ae%b0%e5%bd%95">https://x-file-storage.xuyanwu.cn/#/%E5%9F%BA%E7%A1%80%E5%8A%9F%E8%83%BD?id=%e4%bf%9d%e5%ad%98%e4%b8%8a%e4%bc%a0%e8%ae%b0%e5%bd%95</a>
 */
@Service
public class FileDetailServiceImpl implements FileDetailService {
    /**
     * 文件信息 Mapper
     */
    private FileDetailMapper fileDetailMapper;
    /**
     * 文件分片信息 Mapper
     */
    private FilePartDetailMapper filePartDetailMapper;

    public FileDetailServiceImpl(FileDetailMapper fileDetailMapper, FilePartDetailMapper filePartDetailMapper) {
        this.fileDetailMapper = fileDetailMapper;
        this.filePartDetailMapper = filePartDetailMapper;
    }

    /**
     * 保存文件信息到数据库
     */
    @Override
    public boolean save(FileInfo fileInfo) {
        FileDetail fileDetail = FileConvertor.toFileDetail(fileInfo);
        Integer retCount = this.fileDetailMapper.insert(fileDetail);
        Boolean isSuccess = Objects.nonNull(retCount) && 0 < retCount;
        if (isSuccess) {
            fileInfo.setId(fileDetail.getId());
        }
        return isSuccess;
    }

    /**
     * 更新文件记录，可以根据文件 ID 或 URL 来更新文件记录，
     * 主要用在手动分片上传文件-完成上传，作用是更新文件信息
     */
    @Override
    public void update(FileInfo fileInfo) {
        FileDetail fileDetail = FileConvertor.toFileDetail(fileInfo);
        this.fileDetailMapper.updateByIdOrUrl(fileDetail);
    }

    /**
     * 根据 url 查询文件信息
     */
    @Override
    public FileInfo getByUrl(String url) {
        FileDetail fileDetail = this.fileDetailMapper.findByUrl(url);
        return FileConvertor.toFileInfo(fileDetail);
    }

    /**
     * 根据 url 删除文件信息
     */
    @Override
    public boolean delete(String url) {
        this.fileDetailMapper.deleteByUrl(url);
        return true;
    }

    /**
     * 保存文件分片信息
     *
     * @param filePartInfo 文件分片信息
     */
    @Override
    public void saveFilePart(FilePartInfo filePartInfo) {
        FilePartDetail filePartDetail = FileConvertor.toFilePartDetail(filePartInfo);
        int retCount = this.filePartDetailMapper.insert(filePartDetail);
        Boolean isSuccess = this.isSuccessCount(retCount);
        if (isSuccess) {
            filePartInfo.setId(filePartDetail.getId());
        }
    }

    /**
     * 删除文件分片信息
     */
    @Override
    public void deleteFilePartByUploadId(String uploadId) {
        this.filePartDetailMapper.deleteByUploadId(uploadId);
    }

    @Override
    public List<FileDetail> findByIds(Collection<String> ids) {
        return this.fileDetailMapper.findByIds(ids);
    }

    @Override
    public void updateTrainStatus(String id, TrainStatusEnum trainStatus) {
        this.fileDetailMapper.updateTrainStatus(id, trainStatus);
    }

    @Override
    public void updateDocumentIds(String id, Collection<String> documentIds) {
        this.fileDetailMapper.updateDocumentIds(id, documentIds);
    }

    @Override
    public Page<FileDetail> findPage(FileDetailQuery fileDetailQuery) {
        return this.fileDetailMapper.findPage(fileDetailQuery);
    }

    /**
     * 是否成功
     *
     * @param retCount 更新结果数
     * @return 是否成功
     */
    private Boolean isSuccessCount(Integer retCount) {
        return Objects.nonNull(retCount) && 0 < retCount;
    }

}
